package com.zhai.infrastructure.persistent.repository;

import cn.bugstack.middleware.db.router.strategy.IDBRouterStrategy;
import com.zhai.domain.activity.event.ActivitySkuStockZeroMessageEvent;
import com.zhai.domain.activity.model.aggregate.CreatePartakeOrderAggregate;
import com.zhai.domain.activity.model.aggregate.CreateQuotaOrderAggregate;
import com.zhai.domain.activity.model.entity.*;
import com.zhai.domain.activity.model.valobj.ActivitySkuStockKeyVO;
import com.zhai.domain.activity.model.valobj.ActivityStateVO;
import com.zhai.domain.activity.model.valobj.UserRaffleOrderStateVO;
import com.zhai.domain.activity.repository.IActivityRepository;
import com.zhai.infrastructure.event.EventPublisher;
import com.zhai.infrastructure.persistent.dao.*;
import com.zhai.infrastructure.persistent.po.*;
import com.zhai.infrastructure.persistent.redis.IRedisService;
import com.zhai.types.common.Constants;
import com.zhai.types.enums.ResponseCode;
import com.zhai.types.exception.AppException;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RLock;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.zhai.types.common.Constants.RedisKey.*;

/**
 * @Description: 活动仓储
 * @ClassName: ActivityRepository
 * @Author: zhaiyongxin
 * @Date: 2025/2/19 17:24
 * @Version: 1.0
 */
@Slf4j
@Repository
public class ActivityRepository implements IActivityRepository {

    @Resource
    private IRaffleActivitySkuDao activitySkuDao;
    @Resource
    private IRaffleActivityDao activityDao;
    @Resource
    private IRaffleActivityCountDao activityCountDao;
    @Resource
    private IRaffleActivityOrderDao activityOrderDao;
    @Resource
    private IRaffleActivityAccountDao activityAccountDao;
    @Resource
    private IRedisService redisService;
    @Resource
    private IDBRouterStrategy dbRouter;
    @Resource
    private TransactionTemplate transactionTemplate;
    @Resource
    private EventPublisher eventPublisher;
    @Resource
    private ActivitySkuStockZeroMessageEvent activitySkuStockZeroMessageEvent;
    @Resource
    private IUserRaffleOrderDao userRaffleOrderDao;
    @Resource
    private IRaffleActivityAccountMonthDao activityAccountMonthDao;
    @Resource
    private IRaffleActivityAccountDayDao activityAccountDayDao;


    @Override
    public ActivitySkuEntity queryActivitySku(Long sku) {
        RaffleActivitySku raffleActivitySku = activitySkuDao.queryActivitySku(sku);
        return ActivitySkuEntity.builder()
                .sku(raffleActivitySku.getSku())
                .activityId(raffleActivitySku.getActivityId())
                .activityCountId(raffleActivitySku.getActivityCountId())
                .stockCount(raffleActivitySku.getStockCount())
                .stockCountSurplus(raffleActivitySku.getStockCountSurplus())
                .build();
    }

    @Override
    public List<ActivitySkuEntity> queryActivitySkuByActivityId(Long activityId) {
        List<RaffleActivitySku> raffleActivitySkuList = activitySkuDao.queryActivitySkuByActivityId(activityId);
        List<ActivitySkuEntity> activitySkuEntities = new ArrayList<>(raffleActivitySkuList.size());
        for (RaffleActivitySku raffleActivitySku : raffleActivitySkuList) {
            ActivitySkuEntity activitySkuEntity = ActivitySkuEntity.builder()
                    .sku(raffleActivitySku.getSku())
                    .activityId(raffleActivitySku.getActivityId())
                    .activityCountId(raffleActivitySku.getActivityCountId())
                    .stockCount(raffleActivitySku.getStockCount())
                    .stockCountSurplus(raffleActivitySku.getStockCountSurplus())
                    .build();
            activitySkuEntities.add(activitySkuEntity);
        }
        return activitySkuEntities;
    }

    @Override
    public Integer queryRaffleActivityAccountDayPartakeCount(Long activityId, String userId) {
        RaffleActivityAccountDay raffleActivityAccountDay = new RaffleActivityAccountDay();
        raffleActivityAccountDay.setActivityId(activityId);
        raffleActivityAccountDay.setUserId(userId);
        raffleActivityAccountDay.setDay(raffleActivityAccountDay.currentDay());
        Integer dayPartakeCount = activityAccountDayDao.queryRaffleActivityAccountDayPartakeCount(raffleActivityAccountDay);
        return null == dayPartakeCount ? 0 : dayPartakeCount;
    }

    @Override
    public List<Long> querySkuStockList() {
        String cacheKey = ACTIVITY_SKU_LIST_KEY;
        List<Long> skuList = redisService.getValue(cacheKey);
        if (null != skuList) {
            return skuList;
        }
        List<RaffleActivitySku> raffleActivitySkuList = activitySkuDao.querySkuStockList();
        if (null == raffleActivitySkuList || raffleActivitySkuList.size() == 0) return Collections.emptyList();
        skuList = raffleActivitySkuList.stream().map(RaffleActivitySku::getSku).collect(Collectors.toList());
        redisService.setValue(cacheKey, skuList);
        return skuList;
    }

    @Override
    public ActivityAccountEntity queryActivityAccountEntity(String userId, Long activityId) {
        // 1. 查询总账户额度
        RaffleActivityAccount raffleActivityAccount = activityAccountDao.queryActivityAccountByUserId(RaffleActivityAccount.builder()
                .activityId(activityId)
                .userId(userId)
                .build());

        if (null == raffleActivityAccount) {
            return ActivityAccountEntity.builder()
                    .activityId(activityId)
                    .userId(userId)
                    .totalCount(0)
                    .totalCountSurplus(0)
                    .monthCount(0)
                    .monthCountSurplus(0)
                    .dayCount(0)
                    .dayCountSurplus(0)
                    .build();
        }

        // 组装对象
        ActivityAccountEntity activityAccountEntity = new ActivityAccountEntity();
        activityAccountEntity.setUserId(userId);
        activityAccountEntity.setActivityId(activityId);
        activityAccountEntity.setTotalCount(raffleActivityAccount.getTotalCount());
        activityAccountEntity.setTotalCountSurplus(raffleActivityAccount.getTotalCountSurplus());
        activityAccountEntity.setDayCount(raffleActivityAccount.getDayCount());
        activityAccountEntity.setDayCountSurplus(raffleActivityAccount.getDayCountSurplus());
        activityAccountEntity.setMonthCount(raffleActivityAccount.getMonthCount());
        activityAccountEntity.setMonthCountSurplus(raffleActivityAccount.getMonthCountSurplus());

        return activityAccountEntity;
    }

    /**
     * 查询用户抽奖总次数
     * @param activityId
     * @param userId
     * @return
     */
    @Override
    public Integer queryRaffleActivityAccountTotalPartakeCount(Long activityId, String userId) {
        RaffleActivityAccount raffleActivityAccountReq = new RaffleActivityAccount();
        raffleActivityAccountReq.setActivityId(activityId);
        raffleActivityAccountReq.setUserId(userId);
        RaffleActivityAccount raffleActivityAccount = activityAccountDao.queryActivityAccountByUserId(raffleActivityAccountReq);
        return null == raffleActivityAccount ? 0 : raffleActivityAccount.getTotalCount()-raffleActivityAccount.getTotalCountSurplus();
    }


    @Override
    public ActivityEntity queryRaffleActivityByActivityId(Long activityId) {
        String cacheKey = ACTIVITY_KEY + activityId;
        ActivityEntity activityEntity = redisService.getValue(cacheKey);
        if (activityEntity != null) {
            return activityEntity;
        }
        RaffleActivity raffleActivity = activityDao.queryRaffleActivityByActivityId(activityId);
        if(raffleActivity == null) return null;
        activityEntity = ActivityEntity.builder()
                .activityId(raffleActivity.getActivityId())
                .activityName(raffleActivity.getActivityName())
                .activityDesc(raffleActivity.getActivityDesc())
                .beginDateTime(raffleActivity.getBeginDateTime())
                .endDateTime(raffleActivity.getEndDateTime())
                .strategyId(raffleActivity.getStrategyId())
                .state(ActivityStateVO.valueOf(raffleActivity.getState()))
                .build();
        redisService.setValue(cacheKey, activityEntity);
        return activityEntity;
    }

    @Override
    public ActivityCountEntity queryRaffleActivityCountByActivityCountId(Long activityCountId) {
        String cacheKey = ACTIVITY_COUNT_KEY + activityCountId;
        ActivityCountEntity activityCountEntity = redisService.getValue(cacheKey);
        if (activityCountEntity != null) {
            return activityCountEntity;
        }
        RaffleActivityCount raffleActivityCount = activityCountDao.queryActivityCountByActivityCountId(activityCountId);
        activityCountEntity = ActivityCountEntity.builder()
                .activityCountId(raffleActivityCount.getActivityCountId())
                .totalCount(raffleActivityCount.getTotalCount())
                .dayCount(raffleActivityCount.getDayCount())
                .monthCount(raffleActivityCount.getMonthCount())
                .build();
        redisService.setValue(cacheKey, activityCountEntity);
        return activityCountEntity;
    }

    @Override
    public void
    doSaveOrder(CreateQuotaOrderAggregate createQuotaOrderAggregate) {
        RLock lock = redisService.getLock(Constants.RedisKey.ACTIVITY_ACCOUNT_LOCK + createQuotaOrderAggregate.getUserId() + Constants.UNDERLINE + createQuotaOrderAggregate.getActivityId());
        try {
            lock.lock(3, TimeUnit.SECONDS);
            //下单活动实体
            ActivityOrderEntity activityOrderEntity = createQuotaOrderAggregate.getActivityOrderEntity();
            RaffleActivityOrder raffleActivityOrder = new RaffleActivityOrder();
            raffleActivityOrder.setUserId(activityOrderEntity.getUserId());
            raffleActivityOrder.setSku(activityOrderEntity.getSku());
            raffleActivityOrder.setActivityId(activityOrderEntity.getActivityId());
            raffleActivityOrder.setActivityName(activityOrderEntity.getActivityName());
            raffleActivityOrder.setStrategyId(activityOrderEntity.getStrategyId());
            raffleActivityOrder.setOrderId(activityOrderEntity.getOrderId());
            raffleActivityOrder.setOrderTime(activityOrderEntity.getOrderTime());
            raffleActivityOrder.setTotalCount(activityOrderEntity.getTotalCount());
            raffleActivityOrder.setDayCount(activityOrderEntity.getDayCount());
            raffleActivityOrder.setMonthCount(activityOrderEntity.getMonthCount());
            raffleActivityOrder.setState(activityOrderEntity.getState().getCode());
            raffleActivityOrder.setOutBusinessNo(activityOrderEntity.getOutBusinessNo());

            //账户对象实体 - 总
            RaffleActivityAccount raffleActivityAccount = new RaffleActivityAccount();
            raffleActivityAccount.setUserId(createQuotaOrderAggregate.getUserId());
            raffleActivityAccount.setActivityId(createQuotaOrderAggregate.getActivityId());
            raffleActivityAccount.setTotalCount(createQuotaOrderAggregate.getTotalCount());
            raffleActivityAccount.setTotalCountSurplus(createQuotaOrderAggregate.getTotalCount());
            raffleActivityAccount.setDayCount(createQuotaOrderAggregate.getDayCount());
            raffleActivityAccount.setDayCountSurplus(createQuotaOrderAggregate.getDayCount());
            raffleActivityAccount.setMonthCount(createQuotaOrderAggregate.getMonthCount());
            raffleActivityAccount.setMonthCountSurplus(createQuotaOrderAggregate.getMonthCount());

            //账户对象实体-月
            RaffleActivityAccountMonth raffleActivityAccountMonth = new RaffleActivityAccountMonth();
            raffleActivityAccountMonth.setUserId(createQuotaOrderAggregate.getUserId());
            raffleActivityAccountMonth.setActivityId(createQuotaOrderAggregate.getActivityId());
            raffleActivityAccountMonth.setMonth(raffleActivityAccountMonth.currentMonth());
            raffleActivityAccountMonth.setMonthCount(createQuotaOrderAggregate.getMonthCount());
            raffleActivityAccountMonth.setMonthCountSurplus(createQuotaOrderAggregate.getMonthCount());

            //账户对象实体-日
            RaffleActivityAccountDay raffleActivityAccountDay = new RaffleActivityAccountDay();
            raffleActivityAccountDay.setUserId(createQuotaOrderAggregate.getUserId());
            raffleActivityAccountDay.setActivityId(createQuotaOrderAggregate.getActivityId());
            raffleActivityAccountDay.setDayCount(createQuotaOrderAggregate.getDayCount());
            raffleActivityAccountDay.setDayCountSurplus(createQuotaOrderAggregate.getDayCount());
            raffleActivityAccountDay.setDay(raffleActivityAccountDay.currentDay());


            // 以用户ID作为切分键，通过 doRouter 设定路由【这样就保证了下面的操作，都是同一个链接下，也就保证了事务的特性】
            dbRouter.doRouter(createQuotaOrderAggregate.getUserId());

            transactionTemplate.execute(status -> {
                try {
                    // 1.写入订单
                    activityOrderDao.insert(raffleActivityOrder);
                    // 2.更新账户信息
                    int count = activityAccountDao.updateAccountQuota(raffleActivityAccount);
                    if (count == 0) {
                        activityAccountDao.insert(raffleActivityAccount);
                    }
                    // 更新月账户
                    activityAccountMonthDao.addAccountQuota(raffleActivityAccountMonth);
                    // 更新日账户
                    activityAccountDayDao.addAccountQuota(raffleActivityAccountDay);
                    return 1;
                } catch (DuplicateKeyException e) {
                    status.setRollbackOnly();
                    log.error("写入订单记录，唯一索引冲突 userId: {} activityId: {} sku: {}", activityOrderEntity.getUserId(), activityOrderEntity.getActivityId(), activityOrderEntity.getSku(), e);
                    throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode());
                }
            });
        } finally {
            dbRouter.clear();
            lock.unlock();
        }

    }

    @Override
    public void cacheActivitySkuStockCount(String cacheKey, Integer stockCount) {
        if (redisService.isExists(cacheKey)) return;
        redisService.setAtomicLong(cacheKey, stockCount);
    }

    /**
     * 扣减sku库存
     * @param sku
     * @param endTime
     * @return
     */
    @Override
    public boolean subtractActivitySkuStock(Long sku, String cacheKey, Date endTime) {
        // 1.redis扣减库存
        long surplus = redisService.decr(cacheKey);
        if (surplus < 0) {
            redisService.setAtomicLong(cacheKey, 0);
            return false;
        } else if (surplus == 0){
            //发送消息队列，更新数据库sku库存为0，并且删除所有redis延迟锁
            eventPublisher.publish(activitySkuStockZeroMessageEvent.topic(), activitySkuStockZeroMessageEvent.buildEventMessage(sku));
        }
        // 2.写入延迟队列 同时设置锁过期时间
        String lockKey = cacheKey + Constants.UNDERLINE + surplus;
        long expireMillis = endTime.getTime() - System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1);
        Boolean lock = redisService.setNx(lockKey, expireMillis, TimeUnit.SECONDS);
        if (!lock){
            log.info("活动sku库存加锁失败 {}", lockKey);
        }
        return lock;
    }

    @Override
    public void activitySkuStockConsumeSendQueue(ActivitySkuStockKeyVO activitySkuStockKeyVO) {
        Long sku = activitySkuStockKeyVO.getSku();
        String cacheKey = ACTIVITY_SKU_COUNT_QUERY_KEY + sku;
        RBlockingQueue<Object> blockingQueue = redisService.getBlockingQueue(cacheKey);
        RDelayedQueue<Object> delayedQueue = redisService.getDelayedQueue(blockingQueue);
        delayedQueue.offer(activitySkuStockKeyVO, 3, TimeUnit.SECONDS);
    }

    @Override
    public ActivitySkuStockKeyVO takeQueueValue(Long sku) {
        String cacheKey = null == sku ? ACTIVITY_SKU_COUNT_QUERY_KEY : ACTIVITY_SKU_COUNT_QUERY_KEY + sku;
        RBlockingQueue<ActivitySkuStockKeyVO> blockingQueue = redisService.getBlockingQueue(cacheKey);
        return blockingQueue.poll();
    }

    /**
     * 扣减库存
     * @param activitySkuStockKeyVO
     */
    @Override
    public void updateActivitySkuStock(ActivitySkuStockKeyVO activitySkuStockKeyVO) {
        activitySkuDao.updateActivitySkuStock(activitySkuStockKeyVO.getSku());
    }

    @Override
    public void clearActivitySkuStock(Long sku) {
        activitySkuDao.clearActivitySkuStock(sku);
    }

    @Override
    public void clearQueueValue(Long sku) {
        String cacheKey = null == sku ? ACTIVITY_SKU_COUNT_QUERY_KEY : ACTIVITY_SKU_COUNT_QUERY_KEY + sku;
        RBlockingQueue<Object> blockingQueue = redisService.getBlockingQueue(cacheKey);
        blockingQueue.clear();
        RDelayedQueue<Object> delayedQueue = redisService.getDelayedQueue(blockingQueue);
        delayedQueue.clear();
    }

    /**
     * 查询未使用的订单
     * @param partakeRaffleActivityEntity
     * @return
     */
    @Override
    public UserRaffleOrderEntity queryUnusedActivityOrder(PartakeRaffleActivityEntity partakeRaffleActivityEntity) {
        UserRaffleOrder userRaffleOrderReq = new UserRaffleOrder();
        userRaffleOrderReq.setActivityId(partakeRaffleActivityEntity.getActivityId());
        userRaffleOrderReq.setUserId(partakeRaffleActivityEntity.getUserId());
        UserRaffleOrder userRaffleOrderRes = userRaffleOrderDao.queryUnusedActivityOrder(userRaffleOrderReq);
        if (userRaffleOrderRes == null) {return null;}
        //封装返回结果
        UserRaffleOrderEntity userRaffleOrderEntity = new UserRaffleOrderEntity();
        userRaffleOrderEntity.setActivityId(userRaffleOrderRes.getActivityId());
        userRaffleOrderEntity.setUserId(userRaffleOrderRes.getUserId());
        userRaffleOrderEntity.setActivityName(userRaffleOrderRes.getActivityName());
        userRaffleOrderEntity.setStrategyId(userRaffleOrderRes.getStrategyId());
        userRaffleOrderEntity.setOrderId(userRaffleOrderRes.getOrderId());
        userRaffleOrderEntity.setOrderTime(userRaffleOrderRes.getOrderTime());
        userRaffleOrderEntity.setOrderState(UserRaffleOrderStateVO.valueOf(userRaffleOrderRes.getOrderState()));
        return userRaffleOrderEntity;
    }

    /**
     * 查询活动账户总额度
     * @param activityId
     * @param userId
     * @return
     */
    @Override
    public ActivityAccountEntity queryActivityAccountByUserId(Long activityId, String userId) {
        RaffleActivityAccount raffleActivityAccountReq = new RaffleActivityAccount();
        raffleActivityAccountReq.setActivityId(activityId);
        raffleActivityAccountReq.setUserId(userId);
        RaffleActivityAccount raffleActivityAccountRes = activityAccountDao.queryActivityAccountByUserId(raffleActivityAccountReq);
        if (raffleActivityAccountRes == null) return null;
        return ActivityAccountEntity.builder()
                .activityId(raffleActivityAccountRes.getActivityId())
                .userId(raffleActivityAccountRes.getUserId())
                .totalCount(raffleActivityAccountRes.getTotalCount())
                .totalCountSurplus(raffleActivityAccountRes.getTotalCountSurplus())
                .monthCount(raffleActivityAccountRes.getMonthCount())
                .monthCountSurplus(raffleActivityAccountRes.getMonthCountSurplus())
                .dayCount(raffleActivityAccountRes.getDayCount())
                .dayCountSurplus(raffleActivityAccountRes.getDayCountSurplus())
                .build();
    }

    @Override
    public ActivityAccountMonthEntity queryActivityAccountMonthByUserId(Long activityId, String userId, String month) {
        RaffleActivityAccountMonth raffleActivityAccountMonthReq = new RaffleActivityAccountMonth();
        raffleActivityAccountMonthReq.setActivityId(activityId);
        raffleActivityAccountMonthReq.setUserId(userId);
        raffleActivityAccountMonthReq.setMonth(month);
        RaffleActivityAccountMonth raffleActivityAccountMonthRes = activityAccountMonthDao.queryActivityAccountMonthByUserId(raffleActivityAccountMonthReq);
        if (raffleActivityAccountMonthRes == null) return null;
        return ActivityAccountMonthEntity.builder()
                .activityId(raffleActivityAccountMonthRes.getActivityId())
                .userId(raffleActivityAccountMonthRes.getUserId())
                .month(month)
                .monthCount(raffleActivityAccountMonthRes.getMonthCount())
                .monthCountSurplus(raffleActivityAccountMonthRes.getMonthCountSurplus())
                .build();
    }

    @Override
    public ActivityAccountDayEntity queryActivityAccountDayByUserId(Long activityId, String userId, String day) {
        RaffleActivityAccountDay raffleActivityAccountDayReq = new RaffleActivityAccountDay();
        raffleActivityAccountDayReq.setActivityId(activityId);
        raffleActivityAccountDayReq.setUserId(userId);
        raffleActivityAccountDayReq.setDay(day);
        RaffleActivityAccountDay raffleActivityAccountDayRes = activityAccountDayDao.queryActivityAccountDayByUserId(raffleActivityAccountDayReq);
        if (raffleActivityAccountDayRes == null) return null;
        return ActivityAccountDayEntity.builder()
                .activityId(raffleActivityAccountDayRes.getActivityId())
                .userId(raffleActivityAccountDayRes.getUserId())
                .day(day)
                .dayCount(raffleActivityAccountDayRes.getDayCount())
                .dayCountSurplus(raffleActivityAccountDayRes.getDayCountSurplus())
                .build();
    }

    /**
     * 保存下单聚合对象
     * @param createPartakeOrderAggregate
     */
    @Override
    public void saveCreatePartakeOrderAggregate(CreatePartakeOrderAggregate createPartakeOrderAggregate) {
        try {
            Long activityId = createPartakeOrderAggregate.getActivityId();
            String userId = createPartakeOrderAggregate.getUserId();

            ActivityAccountEntity activityAccountEntity = createPartakeOrderAggregate.getActivityAccountEntity();
            ActivityAccountMonthEntity activityAccountMonthEntity = createPartakeOrderAggregate.getActivityAccountMonthEntity();
            ActivityAccountDayEntity activityAccountDayEntity = createPartakeOrderAggregate.getActivityAccountDayEntity();
            UserRaffleOrderEntity userRaffleOrderEntity = createPartakeOrderAggregate.getUserRaffleOrderEntity();

            // 以用户ID作为切分键，通过 doRouter 设定路由【这样就保证了下面的操作，都是同一个链接下，也就保证了事务的特性】
            dbRouter.doRouter(userId);

            transactionTemplate.execute(status -> {
                try {
                    // 扣减总账户额度
                    int totalCount = activityAccountDao.updateActivityAccountSubtractionQuota(
                            RaffleActivityAccount.builder()
                                    .activityId(activityAccountEntity.getActivityId())
                                    .userId(activityAccountEntity.getUserId())
                                    .build());
                    if (totalCount != 1) {
                        status.setRollbackOnly();
                        log.warn("写入创建参与活动记录，更新总账户额度不足，异常 userId: {} activityId: {}", userId, activityId);
                        throw new AppException(ResponseCode.ACCOUNT_QUOTA_ERROR.getCode(), ResponseCode.ACCOUNT_QUOTA_ERROR.getInfo());
                    }
                    // 扣减月额度 月额度存在时更新 不存在时新增
                    if (createPartakeOrderAggregate.isExistAccountMonth()){
                        int monthCount = activityAccountMonthDao.updateActivityAccountMonthSubtractionQuota(
                            RaffleActivityAccountMonth.builder()
                                    .activityId(activityAccountMonthEntity.getActivityId())
                                    .userId(activityAccountMonthEntity.getUserId())
                                    .month(activityAccountMonthEntity.getMonth())
                                    .build());
                        if (monthCount != 1) {
                            status.setRollbackOnly();
                            log.warn("写入创建参与活动记录，更新月账户额度不足，异常 userId: {} activityId: {}", userId, activityId);
                            throw new AppException(ResponseCode.ACCOUNT_MONTH_QUOTA_ERROR.getCode(), ResponseCode.ACCOUNT_MONTH_QUOTA_ERROR.getInfo());
                        }
                    } else {
                        activityAccountMonthDao.insertActivityAccountMonth(
                                RaffleActivityAccountMonth.builder()
                                        .activityId(activityAccountMonthEntity.getActivityId())
                                        .userId(activityAccountMonthEntity.getUserId())
                                        .month(activityAccountMonthEntity.getMonth())
                                        .monthCount(activityAccountMonthEntity.getMonthCount())
                                        .monthCountSurplus(activityAccountMonthEntity.getMonthCountSurplus() - 1)
                                        .build());

                        //更新总账户额度中的月额度
//                        activityAccountDao.updateActivityAccountMonthSurplusImageQuota(
//                                RaffleActivityAccount.builder()
//                                        .activityId(activityAccountEntity.getActivityId())
//                                        .userId(activityAccountEntity.getUserId())
//                                        .monthCountSurplus(activityAccountEntity.getMonthCountSurplus())
//                                        .build()
//                        );
                    }
                    // 3. 创建或更新日账户，true - 存在则更新，false - 不存在则插入
                    if (createPartakeOrderAggregate.isExistAccountDay()) {
                        int updateDayCount = activityAccountDayDao.updateActivityAccountDaySubtractionQuota(RaffleActivityAccountDay.builder()
                                .userId(userId)
                                .activityId(activityId)
                                .day(activityAccountDayEntity.getDay())
                                .build());
                        if (1 != updateDayCount) {
                            // 未更新成功则回滚
                            status.setRollbackOnly();
                            log.warn("写入创建参与活动记录，更新日账户额度不足，异常 userId: {} activityId: {} day: {}", userId, activityId, activityAccountDayEntity.getDay());
                            throw new AppException(ResponseCode.ACCOUNT_DAY_QUOTA_ERROR.getCode(), ResponseCode.ACCOUNT_DAY_QUOTA_ERROR.getInfo());
                        }
                    } else {
                        activityAccountDayDao.insertActivityAccountDay(RaffleActivityAccountDay.builder()
                                .userId(activityAccountDayEntity.getUserId())
                                .activityId(activityAccountDayEntity.getActivityId())
                                .day(activityAccountDayEntity.getDay())
                                .dayCount(activityAccountDayEntity.getDayCount())
                                .dayCountSurplus(activityAccountDayEntity.getDayCountSurplus() - 1)
                                .build());
                        // 新创建日账户，则更新总账表中日镜像额度
//                        activityAccountDao.updateActivityAccountDaySurplusImageQuota(RaffleActivityAccount.builder()
//                                .userId(userId)
//                                .activityId(activityId)
//                                .dayCountSurplus(activityAccountEntity.getDayCountSurplus())
//                                .build());
                    }

                    // 4. 写入参与活动订单
                    userRaffleOrderDao.insert(UserRaffleOrder.builder()
                            .userId(userRaffleOrderEntity.getUserId())
                            .activityId(userRaffleOrderEntity.getActivityId())
                            .activityName(userRaffleOrderEntity.getActivityName())
                            .strategyId(userRaffleOrderEntity.getStrategyId())
                            .orderId(userRaffleOrderEntity.getOrderId())
                            .orderTime(userRaffleOrderEntity.getOrderTime())
                            .orderState(userRaffleOrderEntity.getOrderState().getCode())
                            .build());

                    return 1;
                } catch (DuplicateKeyException e) {
                    status.setRollbackOnly();
                    log.error("写入订单记录，唯一索引冲突 userId: {} activityId: {}", userId, activityId, e);
                    throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode());
                }
            });

        } finally {
            dbRouter.clear();
        }

    }


}
